package online.heycm.platform.rocketmq.consumer;

import java.lang.reflect.Method;
import java.util.Map;
import java.util.concurrent.ConcurrentHashMap;
import lombok.extern.slf4j.Slf4j;
import online.heycm.platform.common.entity.constant.Constant;
import online.heycm.platform.common.entity.exception.Assert;
import online.heycm.platform.rocketmq.common.entity.Context;
import online.heycm.platform.rocketmq.common.entity.Event;
import org.slf4j.MDC;

/**
 * @author heycm
 * @since 2023/12/9 14:26
 */
@Slf4j
public class EventRegistry {

    private static final Map<String, Method> EVENTS = new ConcurrentHashMap<>();
    private static final Map<String, EventConsumer> BEANS = new ConcurrentHashMap<>();

    public static void register(EventConsumer eventConsumer) {
        Assert.notNull(eventConsumer, "EventConsumer is not allowed null.");

        Class<? extends EventConsumer> clazz = eventConsumer.getClass();
        for (Method method : clazz.getDeclaredMethods()) {
            String eventName = method.getName();
            Assert.isTrue(!EVENTS.containsKey(eventName), "注册事件名称冲突: " + eventName);
            Class<?>[] parameterTypes = method.getParameterTypes();
            Assert.isTrue(parameterTypes.length == 1, "不支持的事件: " + eventName);
            Assert.isTrue(parameterTypes[0].getName().equals(Context.class.getName()), "不支持的事件: " + eventName);
            log.info("注册事件监听: {}", eventName);
            EVENTS.put(eventName, method);
            BEANS.put(eventName, eventConsumer);
        }
    }

    public static void onMessage(Event event) {
        MDC.put(Constant.TRACE_ID, event.getEventId());
        Method method = EVENTS.get(event.getEventName());
        EventConsumer eventListener = BEANS.get(event.getEventName());
        if (method == null || eventListener == null) {
            log.info("主题[{}]不支持事件: [{}]", event.getEventTopic(), event.getEventName());
            return;
        }
        try {
            method.invoke(eventListener, event.getContext());
        } catch (Exception e) {
            e.printStackTrace();
            throw new RuntimeException(e.getMessage());
        }
    }
}
